home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / DYN401.ZIP / kernel / kernel.c < prev    next >
C/C++ Source or Header  |  1997-04-12  |  47KB  |  1,948 lines

  1.  
  2.  
  3.  
  4.  
  5. /*
  6.  *
  7.  *    Copyright (c) 1993-1996 Algorithms Corporation
  8.  *    3020 Liberty Hills Drive
  9.  *    Franklin, TN  37067
  10.  *
  11.  *    ALL RIGHTS RESERVED.
  12.  *
  13.  *
  14.  *
  15.  */
  16.  
  17.  
  18.  
  19. #include <string.h>
  20. #include <time.h>
  21. #if    !defined(unix) && !defined(__MWERKS__)
  22. #include <dos.h>
  23. #endif
  24. #include "generics.h"
  25.  
  26. #if    defined(MSC32)  ||  defined(BC32)  ||  defined(SYMC32)
  27. #include <signal.h>
  28. #include <setjmp.h>
  29. #define    USE_SIGNAL
  30. #endif
  31.  
  32. #ifdef    BOEHM_GC    /*  use the Hans-J. Boehm Garbage Collector (boehm@mti.sgi.com)  */
  33. #include "gc.h"
  34. #define    free(x)
  35. #endif
  36.  
  37.  
  38. #if    defined(MSC16)  ||  defined(WATCOM16)  ||  defined(BC16)  ||  defined(SYMC16)
  39. #define SEGMENTED_MEMORY
  40. #endif
  41.  
  42. #if    defined(sparc)  ||  defined(MSC32)  ||  defined(BC32)  ||  defined(unix)  ||  defined(SYMC32)
  43. #define ALIGN4
  44. #else
  45. #define ALIGN2
  46. #endif
  47.  
  48. #ifdef    BC32
  49. #pragma inline
  50. #endif
  51.  
  52.  
  53. #include "kernels.h"
  54.  
  55. #include "object.iv"
  56.  
  57. #include "method.iv"
  58.  
  59. #include "genfun.iv"
  60.  
  61. #include "behavior.iv"
  62.  
  63.  
  64. /*  keep list of global memory ranges that should be marked during garbage
  65.     collection.  */
  66.  
  67. typedef    struct    memory_range  {    
  68.     struct    memory_range    *next;
  69.     struct    memory_range    *prev;
  70.     void    *beg;
  71.     long    size;
  72. }    GMR;
  73.  
  74. #define set_class(a, b)        a->cls = b
  75.  
  76. #define SCIV(x)    ((Behavior_iv_t *) ((object)(x) + 1))  /* Behavior_iv_t IVs */
  77.  
  78.  
  79. #ifdef    ALIGN4   /* align 4 byte */
  80. #define EVEN(x)        ((((unsigned long)(x) + 3) >> 2) << 2)
  81. #else    
  82. #define EVEN(x)        ((x) + ((x) % 2))
  83. #endif
  84.  
  85.  
  86. int    _CheckObjects_ = 1;        /*  turn object checking on/off  */
  87.  
  88. object    _LastGeneric_ = NULL;        /*  last generic function called  */
  89.  
  90. int    _no_context_switch = 0;   /*  if set inhibits all context switching */
  91.  
  92. int    _tick_count = 1;
  93.  
  94. CRITICALSECTION  _CI_CS_;        /*  used during class initialization  */
  95.  
  96.  
  97. #if    defined(__WATCOMC__)  &&  defined(__cplusplus)
  98. extern    "C"    void    (*__dynace_yield)(void) = NULL;
  99. #else
  100. void    (*__dynace_yield)(void) = NULL;
  101. #endif
  102.  
  103.  
  104. static    int    TRACES = TRACE_OFF;    /*  turn tracing off/on        */
  105. static    object    MCL = NULL;        /*  master class list        */
  106. static    object    MGL = NULL;        /*  master generic function list  */
  107. static    object    MML = NULL;        /*  master method list        */
  108. static    int    CID = 0;        /*  next class id        */
  109. static    int    GID = 0;        /*  next generic id        */
  110. static    int    Crows = 199;        /*  cache rows (generics)    */
  111. static    int    Ccols = 59;        /*  cache cols (classes)    */
  112. static    long    SIG1 = 0L;        /*  class signatures        */
  113. static    long    SIG2;
  114. static    char    *StackBeg;        /*  pointer to the beginning of the stack  */
  115. static    GMR    *LGMR = NULL;        /*  list of GMR's          */
  116. static    GMR    *FGMR = NULL;        /*  free GMR objects        */
  117. static    int    NUM_CLASSES;        /*  number of classes (max)     */
  118.  
  119. static    CRITICALSECTION  MCL_CS;      /*  and CID  */
  120. static    CRITICALSECTION  MGL_CS;      /*  and GID  */
  121. static    CRITICALSECTION  MML_CS;
  122. static    CRITICALSECTION  GMR_CS;
  123.  
  124. /*  storage statistic variables  */
  125.  
  126. static    long    MBU = 0L;        /*  max bytes used by objects after GC    */
  127. static    long    GBA = -1L;        /*  garbage buffer area                */
  128. static    long    CMU = 0L;        /*  current memory usage by objects     */
  129. static    long    MSU = 0L;        /*  maximum storage used by objects     */
  130.  
  131. #define cache_entry(g, c)        g + c
  132.  
  133. extern    object    Object_c, Behavior_c, Class_c, MetaClass_c;
  134. extern    object    GenericFunction_c, Method_c, Dynace_c;
  135.  
  136. static    object    metaObject, metaClass, metaBehavior, metaMetaClass;
  137. static    object    metaMethod, metaGenericFunction;
  138.  
  139. /*  object status flags  */
  140.  
  141. #define OBJ_FREE    0x8000
  142. #define OBJ_USED    0x4000
  143. #define OBJ_MARKED    0x2000
  144. #define OBJ_MASK    (OBJ_FREE | OBJ_USED | OBJ_MARKED)
  145.  
  146. /*  object allocation types  */
  147.  
  148. #define    ALLOC_HEAP    0x1000
  149. #define    ALLOC_STACK    0x0800
  150. #define    ALLOC_MASK    (ALLOC_HEAP | ALLOC_STACK)
  151.  
  152. #define    ALL_MASK    (OBJ_MASK | ALLOC_MASK)
  153.  
  154. #define GMR_BLOCK_SIZE    20
  155.  
  156.  
  157. /*  Maximum number of immediate (not including inherited) superclasses per
  158.     class.  Arbitrarly set to an unrealisticly large number which should
  159.     never be reached.
  160. */
  161.  
  162. #define MIS    20
  163.  
  164.  
  165.  
  166. /*  Local function declarations   */
  167.  
  168. static    void add_ptr(char *p,unsigned len);
  169. static    struct memory_range *new_gmr(void);
  170. static    void free_gmr(struct memory_range *gmr);
  171. static    void extend_storage(Behavior_iv_t *cv);
  172. static    objrtn Behavior_im_gNew(object self);
  173. static    void mk_subclass_link(object sc,object c);
  174. static    void set_superclass(object obj,object sc);
  175. static    char *strsave(char *x);
  176. static    void new_class(object c,Behavior_iv_t *cv,char *name);
  177. static    objrtn defClass(object cls,char *name,int effective_iv_size,int direct_iv_size,int nipib);
  178. static  objrtn GenericFunction_cm_gNewWithStr(object self, char *name);
  179. static    objrtn Method_cm_gNewMethod(object self, char *name, object cls, object generic, ofun methf, ofun methf2);
  180. static    objrtn Dynace_cm_gSetMemoryBufferArea(object self,long sz);
  181. static    Method_iv_t *find_method(object generic,object cls,int level, object *mo);
  182. static    struct _iv_offset_def_list *mk_sciv_list(struct _iv_offset_def_list *v,object sc);
  183. static    void remove_dup_sc(struct _iv_offset_def_list *v);
  184. static    int calc_offsets(struct _iv_offset_def_list *v);
  185. static    objrtn Object_im_gDispose(object self);
  186. static    void Dyance_cm_gMarkObject(object self,object obj);
  187. static    void Dynace_cm_gMarkRange(object self,char _HUGE **from ,char _HUGE **to );
  188. static    void rebuild_free_list(Behavior_iv_t *cv,int is);
  189. static    void gc_sweep(void);
  190. static    void get_mem_stats(void);
  191. static    objrtn Dynace_cm_gGC(object self);
  192. static    void *Dynace_cm_gRegisterMemory(object self,void *beg,long size);
  193. static    void Dynace_cm_gRemoveRegisteredMemory(object self,void *p);
  194. static    void *Dynace_cm_gChangeRegisteredMemory(object self,void *p,void *beg,long size);
  195. #ifdef    BOEHM_GC
  196. static    void dispose_boehm_gc(object obj, void *p);
  197. #endif
  198.  
  199. #if    !DPP_FASTWIDE
  200. static    void create_cache(int rows,int cols);
  201. static    void free_cache(void);
  202. static    void rebuild_class_indexes(void);
  203. static    void rebuild_generic_indexes(void);
  204. static    objrtn Dynace_cm_gResizeMethodCache(object self,int classes,int generics);
  205. static    void cache_add(int row,int col,object generic,object cls,int level,object meth);
  206. #endif
  207.  
  208. void    *Chkmem(void *p, char *file, int line)
  209. {
  210.     char    buf[90];
  211.     
  212.     if (!p)  {
  213.         sprintf(buf, "\nDynace: Out of memory in %s at line %d.\n", file, line);
  214.         gError(Dynace_c, buf);
  215.     }
  216.     return p;
  217. }
  218.  
  219. #ifdef    SEGMENTED_MEMORY
  220.  
  221.  
  222. typedef    struct  _sl  {        /*  keep list of segment and ranges allocated */
  223.     unsigned    seg;
  224.     unsigned    min_off;
  225.     unsigned    max_off;
  226.     struct    _sl    *next;
  227. }    SL;
  228.  
  229. static    SL    *MSL = NULL;        /*  Master segment list        */
  230.  
  231. static    CRITICALSECTION   MSL_CS;
  232.  
  233.  
  234. static    void    add_ptr(char *p, unsigned len)
  235. {
  236.     register unsigned    seg = FP_SEG(p);
  237.     unsigned    off = FP_OFF(p);
  238.     unsigned    end = off + len;
  239.     SL    *sl;
  240.  
  241.     ENTERCRITICALSECTION(MSL_CS);
  242.     for (sl = MSL ; sl &&  sl->seg != seg ; sl = sl->next);
  243.     if (!sl)  {
  244.         sl = Tcalloc(SL);
  245.         sl->seg = seg;
  246.         sl->min_off = off;
  247.         sl->max_off = end;
  248.         sl->next = MSL;
  249.         MSL = sl;
  250.     } else {
  251.         if (off < sl->min_off)
  252.             sl->min_off = off;
  253.         if (end > sl->max_off)
  254.             sl->max_off = end;
  255.     }
  256.     LEAVECRITICALSECTION(MSL_CS);
  257. }
  258.  
  259. static    int    chk_ptr(char *p, unsigned len)
  260. {
  261.     register unsigned    seg = FP_SEG(p);
  262.     unsigned    off;
  263.     SL    *sl;
  264.     int    r;
  265.  
  266.     ENTERCRITICALSECTION(MSL_CS);
  267.     for (sl = MSL ; sl &&  sl->seg != seg ; sl = sl->next);
  268.     r = sl && (off=FP_OFF(p)) >= sl->min_off  &&  off+len <= sl->max_off;
  269.     LEAVECRITICALSECTION(MSL_CS);
  270.     return r;
  271. }
  272.  
  273. #else
  274.  
  275. static    char    *lowPtr = NULL;
  276. static    char    *highPtr = NULL;
  277.  
  278. static    CRITICALSECTION   PTR_CS;
  279.  
  280. static    void    add_ptr(char *p, unsigned len)
  281. {
  282.     ENTERCRITICALSECTION(PTR_CS);
  283.     if (!lowPtr  ||  p < lowPtr)
  284.         lowPtr = p;
  285.     p += len;
  286.     if (p > highPtr)
  287.         highPtr = p;
  288.     LEAVECRITICALSECTION(PTR_CS);
  289. }
  290.  
  291. #ifdef    ALIGN4
  292. #define chk_ptr(p, len)    (!((unsigned long)(p) & (3)) &&        \
  293.              (char *)(p) >= lowPtr  &&        \
  294.              (char *)(p) <= highPtr - (len))
  295. #else
  296. #define    chk_ptr(p, len)    ((char *)(p) >= lowPtr  &&  (char *)(p) <= highPtr - (len))
  297. #endif
  298.  
  299. #endif
  300.  
  301. static    GMR    *new_gmr(void)
  302. {
  303.     GMR    *r;
  304.     int    i;
  305.  
  306.     if (!FGMR)  {
  307.         FGMR = Tncalloc(GMR, GMR_BLOCK_SIZE);
  308.         for (i=0 ; i != (GMR_BLOCK_SIZE-1) ; ++i)
  309.             FGMR[i].next = FGMR + (i + 1);
  310.     }
  311.     r = FGMR;
  312.     FGMR = FGMR->next;
  313.     return r;
  314. }
  315.  
  316. static    void    free_gmr(GMR *gmr)
  317. {
  318.     gmr->next = FGMR;
  319.     FGMR = gmr;
  320. }
  321.  
  322. #if defined(__sparc__)  &&  !defined(__svr4__)    /* memmove is not available on SunOS */
  323. void    *memmove(void *vto, const void *vfrom, int n)
  324. {
  325.     char    *to = (char *) vto;
  326.     char    *from = (char *) vfrom;
  327.     
  328.     if (to < from)
  329.         while (n--)
  330.             *to++ = *from++;
  331.     else if (to > from)  {
  332.         to   += n;
  333.         from += n;
  334.         while (n--)
  335.             *--to = *--from;
  336.     }
  337.     return vto;
  338. }
  339. #endif
  340.  
  341. #ifdef    USE_SIGNAL
  342.  
  343. static    int    sigsegv_error;
  344. static    jmp_buf    sigsegv_jb;
  345. static    CRITICALSECTION  SSE_CS;
  346.  
  347. static    void    handle_sigsegv(int sig)
  348. {
  349.     sigsegv_error = 1;
  350.     longjmp(sigsegv_jb, 1);
  351. }
  352.  
  353. #endif
  354.  
  355. #define    chk_sptr(p, len)  ((char _HUGE *)(p) > (char _HUGE *) &obj  &&  (char _HUGE *)(p) <= (char _HUGE *)StackBeg - (len))
  356.  
  357. int    IsObj(object obj)
  358. {
  359.     object    cls;
  360.     Behavior_iv_t    *cv;
  361.     int    stack=0, ret=0;
  362. #ifdef    USE_SIGNAL
  363.     void    (*ps)(int);
  364.     ENTERCRITICALSECTION(SSE_CS);
  365.     sigsegv_error = 0;
  366.     ps = signal(SIGSEGV, handle_sigsegv);
  367.     if (setjmp(sigsegv_jb))
  368.         goto done;
  369. #endif
  370.  
  371.     if (!chk_ptr((char *) obj, sizeof(Object_iv_t))  &&
  372.         !(stack=chk_sptr(obj, sizeof(Object_iv_t))))
  373.         goto done;
  374.     if (obj->tag & (~ALL_MASK))
  375.         goto done;
  376.     if ((obj->tag & OBJ_MASK) != OBJ_USED  &&  (obj->tag & OBJ_MASK) != OBJ_MARKED)
  377.         goto done;
  378.     if (stack) {
  379.         if ((obj->tag & ALLOC_MASK) != ALLOC_STACK)
  380.             goto done;
  381.     } else
  382.         if ((obj->tag & ALLOC_MASK) != ALLOC_HEAP)
  383.             goto done;
  384.     if ((obj->tag & OBJ_MASK) == OBJ_USED  &&  obj->siz)
  385.         goto done;
  386.     cls = ClassOf(obj);
  387.     if (!chk_ptr((char *) cls, (sizeof(Behavior_iv_t)+sizeof(Object_iv_t))))
  388.         goto done;
  389.     if ((cls->tag & OBJ_MASK) != OBJ_USED  &&  (cls->tag & OBJ_MASK) != OBJ_MARKED  ||
  390.         (cls->tag & ALLOC_MASK) != ALLOC_HEAP)
  391.         goto done;
  392.     cv = SCIV(cls);
  393.     ret = cv->sig1 == SIG1  &&  cv->sig2 == SIG2;
  394. done:
  395. #ifdef    USE_SIGNAL
  396.     signal(SIGSEGV, ps);
  397.     if (sigsegv_error)
  398.         ret = 0;
  399.     LEAVECRITICALSECTION(SSE_CS);
  400. #endif
  401.     return ret;
  402. }
  403.  
  404. static    int    IsClass(object cls)
  405. {
  406.     Behavior_iv_t    *cv;
  407.  
  408.     if (!chk_ptr((char *) cls, (sizeof(Behavior_iv_t)+sizeof(Object_iv_t))))
  409.         return 0;
  410.     if ((cls->tag & OBJ_MASK) != OBJ_USED  &&  (cls->tag & OBJ_MASK) != OBJ_MARKED  ||
  411.         (cls->tag & ALLOC_MASK) != ALLOC_HEAP)
  412.         return 0;
  413.     cv = SCIV(cls);
  414.     return cv->sig1 == SIG1  &&  cv->sig2 == SIG2;
  415. }
  416.  
  417. #ifndef    BOEHM_GC
  418.  
  419. static    void    extend_storage(Behavior_iv_t *cv)
  420. {
  421.     instance_block    *ib;
  422.     int    i, is, ts;
  423.     free_list    *fl;
  424.  
  425.     is = cv->effective_iv_size;
  426.     ts = is * cv->nipib + sizeof(instance_block);
  427.     ib = (instance_block *) Tncalloc(char, ts);
  428.     add_ptr((char *) ib, ts);
  429.     ib->next = cv->ib;
  430.     cv->ib = ib;
  431.     cv->nib++;
  432.     cv->nai += cv->nipib;
  433.     fl = (free_list *) (ib + 1);
  434.     for (i=0 ; i != cv->nipib ; ++i)  {
  435.         ((object) fl)->tag = (OBJ_FREE | ALLOC_HEAP);
  436.         ((object) fl)->siz = 0;
  437.         fl->next = cv->fl;
  438.         cv->fl = fl;
  439.         fl = (free_list *) ((char *) fl + is);
  440.     }
  441. }
  442.  
  443. #endif
  444.  
  445. imeth    objrtn    Behavior_im_gNew(object self)
  446. {
  447.     object    instance;
  448.     Behavior_iv_t    *cv = SCIV(self);
  449.  
  450.     ENTERCRITICALSECTION(cv->cs);
  451. #ifdef    BOEHM_GC
  452.     instance = (object) Tncalloc(char, cv->effective_iv_size);
  453.     GC_register_finalizer_ignore_self((GC_PTR)instance, (GC_finalization_proc)dispose_boehm_gc, 0, 0, 0);
  454.     add_ptr((char *) instance, cv->effective_iv_size);
  455. #else
  456.     if (!cv->fl  &&  GBA > 0L  &&  CMU > MBU + GBA)
  457.         gGC(Dynace_c);
  458.     if (!cv->fl)
  459.         extend_storage(cv);
  460.     instance = (object) cv->fl;
  461.     cv->fl = cv->fl->next;
  462.     cv->nai--;
  463. #endif
  464.     cv->ni++;
  465.     CMU += cv->effective_iv_size;
  466.     MSU = CMU > MSU ? CMU : MSU;
  467. /*
  468.     instance = (object) Tncalloc(char, cv->effective_iv_size);
  469. */
  470.     set_class(instance, self);
  471.     instance->tag = (OBJ_USED | ALLOC_HEAP);
  472.     instance->siz = 0;
  473.     memset(instance+1, 0, cv->effective_iv_size-EVEN(sizeof(Object_iv_t)));
  474.     LEAVECRITICALSECTION(cv->cs);
  475.     return instance;
  476. }
  477.  
  478. imeth    objrtn    Behavior_im_gStackAlloc(object self, void *p)
  479. {
  480.     object    instance = (object) p;
  481.     Behavior_iv_t    *cv = SCIV(self);
  482.  
  483.     if (!instance)
  484.         gError(Dynace_c, "\nDynace: stack allocation failed.\n");
  485.     set_class(instance, self);
  486.     instance->tag = (OBJ_USED | ALLOC_STACK);
  487.     instance->siz = 0;
  488.     memset(instance+1, 0, cv->effective_iv_size-EVEN(sizeof(Object_iv_t)));
  489.     return instance;
  490. }
  491.  
  492. static    void    mk_subclass_link(object sc, object c)
  493. {
  494.     Behavior_iv_t    *sciv;
  495.     object_list    *t;
  496.  
  497.     sciv = SCIV(sc);
  498.     t = Tcalloc(object_list);
  499.     t->obj = c;
  500.     ENTERCRITICALSECTION(sciv->cs);
  501.     t->next = sciv->direct_subclasses;
  502.     sciv->direct_subclasses = t;
  503.     LEAVECRITICALSECTION(sciv->cs);
  504.  
  505. }
  506.  
  507. static    void    set_superclass(object obj, object sc)
  508. {
  509.     Behavior_iv_t    *cv;
  510.  
  511.     if (sc)  {
  512.         cv = SCIV(obj);
  513.         cv->direct_superclasses = Tcalloc(object);
  514.         cv->direct_superclasses[0] = sc;
  515.         cv->n_direct_superclasses = 1;
  516.         mk_subclass_link(sc, obj);
  517.         cv->all_superclasses = mk_sciv_list(NULL, sc);
  518.         cv->direct_iv_offset  = calc_offsets(cv->all_superclasses);
  519.     }
  520. }
  521.  
  522. static    char    *strsave(char *x)
  523. {
  524.     char    *p = Tncalloc(char, (x ? strlen(x) : 0) + 1);
  525.     if (!p)
  526.         gError(Dynace_c, "Out of memory.\n");
  527.     strcpy(p, x ? x : "");
  528.     return(p);
  529. }
  530.  
  531. static    void    new_class(object c, Behavior_iv_t *cv, char *name)
  532. {
  533.     cv->name = strsave(name);
  534.     ENTERCRITICALSECTION(MCL_CS);
  535.     cv->next = MCL;
  536.     MCL = c;
  537.     cv->id = CID++;
  538.     cv->cache_idx = cv->id % Ccols;
  539.     if (!SIG1)  {
  540.         SIG1 = time(NULL);
  541.         SIG2 = ~SIG1;
  542.     }
  543.     cv->sig1 = SIG1;
  544.     cv->sig2 = SIG2;
  545.     INITIALIZECRITICALSECTION(cv->cs);
  546.     LEAVECRITICALSECTION(MCL_CS);
  547. }
  548.  
  549.  /*  defClass:  used to create kernel classes  */
  550.  
  551. static    objrtn    defClass(object cls, char *name, int effective_iv_size, int direct_iv_size, int nipib)
  552. {
  553.     object    nc;
  554.     Behavior_iv_t    *cv;
  555.  
  556.     nc = Behavior_im_gNew(cls);
  557.     cv = SCIV(nc);
  558.     new_class(nc, cv, name);
  559.     cv->effective_iv_size = EVEN(effective_iv_size);
  560.     cv->direct_iv_size    = EVEN(direct_iv_size);
  561.     cv->nipib = nipib;
  562.     return nc;
  563. }
  564.  
  565. cmeth    objrtn    Class_cm_gFindClass(object self, char *name)
  566. {
  567.     object    c;
  568.     Behavior_iv_t    *cv;
  569.  
  570.     USE(self);
  571.     ENTERCRITICALSECTION(MCL_CS);
  572.     for (c=MCL ; c ; c = cv->next)  {
  573.         cv = SCIV(c);
  574.         if (!strcmp(cv->name, name))
  575.             break;
  576.     }
  577.     LEAVECRITICALSECTION(MCL_CS);
  578.     return c;
  579. }
  580.  
  581. #if 1
  582.  
  583. #define direct_ivs(i) ((char *) i + SCIV(ClassOf(i))->direct_iv_offset)
  584.  
  585. #else
  586.  
  587. static    void    *direct_ivs(object instance)
  588. {
  589.     object    cls = ClassOf(instance);
  590.     Behavior_iv_t    *cv = SCIV(cls);
  591.     return (char *) instance + cv->direct_iv_offset;
  592. }
  593.  
  594. #endif
  595.  
  596. cmeth objrtn    GenericFunction_cm_gNewWithStr(object self, char *name)
  597. {
  598.     object    generic;
  599.     GenericFunction_iv_t    *iv;
  600.  
  601.     generic = Behavior_im_gNew(self);
  602.     iv = (GenericFunction_iv_t *) direct_ivs(generic);
  603.     iv->name = strsave(name);
  604.     iv->cache_idx = Ccols * (iv->id % Crows);
  605.     ENTERCRITICALSECTION(MGL_CS);
  606.     iv->id = GID++;
  607.     iv->next = MGL;
  608.     MGL = generic;
  609.     LEAVECRITICALSECTION(MGL_CS);
  610. #if    DPP_FASTWIDE
  611.     iv->mc = Tncalloc(ofun, NUM_CLASSES);
  612. #endif
  613.     return generic;
  614. }
  615.  
  616. cmeth objrtn
  617. Method_cm_gNewMethod(object    self,
  618.              char    *name,
  619.              object    cls,
  620.              object    generic,
  621.              ofun    methf,
  622.              ofun    methf2)
  623. {
  624.     object        meth;
  625.     Method_iv_t    *miv;
  626. /*    GenericFunction_iv_t *giv;   */
  627.     Behavior_iv_t    *civ;
  628.     object_list    *ml;
  629.  
  630.     ChkArg(cls, 3);
  631.     ChkArg(generic, 4);
  632.     if (!IsClass(cls))
  633.         gError(self, "NewMethod::Method arg 3 is not a class.\n");
  634.     
  635.     meth = Behavior_im_gNew(self);
  636.     miv = (Method_iv_t *) direct_ivs(meth);
  637.     miv->name = strsave(name);
  638.     miv->cls = cls;
  639.     miv->generic = generic;
  640.     miv->meth = methf;
  641.     miv->fmeth = methf2;
  642.     ENTERCRITICALSECTION(MML_CS);
  643.     miv->next = MML;
  644.     MML = meth;
  645. #if 0
  646.     giv = (GenericFunction_iv_t *) direct_ivs(generic);
  647.     ml = Tcalloc(object_list);
  648.     ml->obj = meth;
  649.     ml->next = giv->methods;
  650.     giv->methods = ml;
  651. #endif
  652.     civ = SCIV(cls);
  653.     ml = Tcalloc(object_list);
  654.     ml->obj = meth;
  655.     ENTERCRITICALSECTION(civ->cs);
  656.     ml->next = civ->direct_methods;
  657.     civ->direct_methods = ml;
  658.     LEAVECRITICALSECTION(civ->cs);
  659.     
  660.     LEAVECRITICALSECTION(MML_CS);
  661.     return meth;
  662. }
  663.  
  664.  
  665. /*  method cache  */
  666.  
  667. #if    !DPP_FASTWIDE
  668.  
  669. typedef    struct    _element  {
  670.     object        cls;
  671.     object        generic;
  672.     object        meth;
  673.     int        level;        /*  normal / superclass method  */
  674.     Method_iv_t    *miv;
  675.     struct    _element    *next;
  676. }    element;
  677.  
  678. typedef    struct    _cache  {
  679.     int    rows;        /*  generics    */
  680.     int    cols;        /*  classes    */
  681.     element    **table;
  682.     int    used;
  683.     int    chains;
  684. }    cache;
  685.  
  686. static    cache    *method_cache;
  687.  
  688. static    CRITICALSECTION    MC_CS;
  689.  
  690. static    void    create_cache(int rows, int cols)
  691. {
  692.     method_cache = Tcalloc(cache);
  693.     method_cache->table = Tncalloc(element *, rows * cols);
  694.     method_cache->rows = rows;
  695.     method_cache->cols = cols;
  696. }
  697.  
  698. static    void    free_cache(void)
  699. {
  700.     int    i, n;
  701.     element    *e, *ne;
  702.  
  703.     n = method_cache->rows * method_cache->cols;
  704.     for (i=0 ; i != n ; ++i)
  705.         for (e=method_cache->table[i] ; e ; e=ne)  {
  706.             ne = e->next;
  707.             free(e);
  708.         }
  709.     free(method_cache);
  710. }
  711.  
  712. static    void    rebuild_class_indexes(void)
  713. {
  714.     object    c;
  715.     Behavior_iv_t    *cv;
  716.  
  717.     ENTERCRITICALSECTION(MCL_CS);
  718.     for (c=MCL ; c ; c=cv->next)  {
  719.         cv = SCIV(c);
  720.         cv->cache_idx = cv->id % Ccols;
  721.     }
  722.     LEAVECRITICALSECTION(MCL_CS);
  723. }
  724.  
  725. static    void    rebuild_generic_indexes(void)
  726. {
  727.     object    c;
  728.     GenericFunction_iv_t *cv;
  729.  
  730.     ENTERCRITICALSECTION(MGL_CS);
  731.     for (c=MGL ; c ; c=cv->next)  {
  732.         cv = (GenericFunction_iv_t *) direct_ivs(c);
  733.         cv->cache_idx = Ccols * (cv->id % Crows);
  734.     }
  735.     LEAVECRITICALSECTION(MGL_CS);
  736. }
  737.  
  738. cmeth    objrtn    Dynace_cm_gResizeMethodCache(object self, int classes, int generics)
  739. {
  740.     ENTERCRITICALSECTION(MC_CS);
  741.     free_cache();
  742.     create_cache(Crows = generics, Ccols = classes);
  743.     LEAVECRITICALSECTION(MC_CS);
  744.     rebuild_generic_indexes();
  745.     rebuild_class_indexes();
  746.     return self;
  747. }
  748.  
  749. static    void    cache_add(int row, int col, object generic, object cls, int level, object meth)
  750. {
  751. /*    int    pos = method_cache->cols * (row % method_cache->rows) +    col % method_cache->cols;  */
  752.     int    pos = cache_entry(row, col);
  753.     element    *e;
  754.  
  755. /*
  756.     The following code is needed (instead of the Tcalloc) because in
  757.     out-of-memory conditions the gError call will need more elements
  758.     which won't be available because of the lack of memory.  We can
  759.     just avoid the problem by not adding it to the cache.
  760. */
  761.  
  762.     e = (element *) calloc(1, sizeof(element));
  763.     if (!e)
  764.         return;
  765.  
  766. /*    e = Tcalloc(element);     */
  767.  
  768.     e->generic = generic;
  769.     e->cls = cls;
  770.     e->meth = meth;
  771.     e->level = level;
  772.     e->miv = (Method_iv_t *) direct_ivs(meth);
  773.     if (e->next = method_cache->table[pos])
  774.         method_cache->chains++;
  775.     method_cache->table[pos] = e;
  776.     method_cache->used++;
  777. }
  778.  
  779. #endif /* !DPP_FASTWIDE */
  780.  
  781.  
  782. cmeth    objrtn    Dynace_cm_gSetMemoryBufferArea(object self, long sz)
  783. {
  784.     GBA = sz;
  785.     return self;
  786. }
  787.  
  788. /*  Depth-first search  */
  789.  
  790. static    Method_iv_t *
  791. find_method(object    generic,
  792.         object    cls,
  793.         int        level,
  794.         object    *mo)
  795. {
  796.     object_list    *ml;
  797.     Method_iv_t    *miv;
  798.     Behavior_iv_t    *civ;
  799.     int    i;
  800.  
  801.     /*  check if this class implements the generic  */
  802.  
  803.     civ = SCIV(cls);
  804.     if (level == 1) {
  805.         ENTERCRITICALSECTION(civ->cs);
  806.         for (ml=civ->direct_methods ; ml ; ml=ml->next)  {
  807.             miv = (Method_iv_t *) direct_ivs(ml->obj);
  808.             if (miv->generic == generic)  {
  809.                 *mo = ml->obj;
  810.                 LEAVECRITICALSECTION(civ->cs);
  811.                 return miv;
  812.             }
  813.         }
  814.         LEAVECRITICALSECTION(civ->cs);
  815.     }
  816.  
  817.     /*  check the super classes  */
  818.  
  819.     for (i=0 ; i < civ->n_direct_superclasses ; ++i)
  820.         if (miv = find_method(generic, civ->direct_superclasses[i], 1, mo))
  821.             return miv;
  822.     
  823.     return NULL;
  824. }
  825.  
  826.  
  827. #define    tname(x)    (x->name ? x->name : "unnamed")
  828. #define T_ON(x)        x->trace == TRACE_ON
  829. #define T_NOFF(x)    x->trace != TRACE_OFF
  830.  
  831.  
  832. static    void    tracefn(object i, GenericFunction_iv_t *giv, object mo)
  833.                         /*  first arg to generic        */
  834.                                    /*  generic instance vars        */
  835.                          /*  method object            */
  836. {
  837.     int    aClass = IsaClass(i);
  838.     Behavior_iv_t    *cv = aClass ? SCIV(i) : SCIV(ClassOf(i));
  839.     Method_iv_t    *miv = (Method_iv_t *) direct_ivs(mo);
  840.     Behavior_iv_t    *cv2 = SCIV(miv->cls);
  841.     char    buf[100];
  842.     int    none_off, any_on;
  843.     int    traces = TRACES;
  844.  
  845.     TRACES = TRACE_OFF;    /*  prevent recursive calls  */
  846.     none_off = T_NOFF(cv)  &&  T_NOFF(cv2)  &&  T_NOFF(giv)  &&  T_NOFF(miv);
  847.     any_on = T_ON(cv)  ||  T_ON(cv2)  ||  T_ON(giv)  ||  T_ON(miv);
  848.     if (none_off  &&  (traces == TRACE_ALL  ||  any_on))  {
  849.         if (aClass)
  850.             sprintf(buf, "Trace: %s(class %s) -> ",
  851.                    tname(giv), tname(cv));
  852.         else
  853.             sprintf(buf, "Trace: %s(%s instance) -> ",
  854.                    tname(giv), tname(cv));
  855.         sprintf(buf+strlen(buf), "%s::%s\n", tname(miv), tname(cv2));
  856.         gTracePrint(Dynace_c, buf);
  857.     }
  858.     TRACES = traces;
  859. }
  860.  
  861.  
  862. /* very similar to gFindMethod and gFindMethodObject */
  863. /* (if this function changes change the others) */
  864.  
  865. /*  This one aborts the program if it can't find the method    */
  866. /*  This one also performs object checking, yielding and tracing*/
  867. /*  Used by generics                        */
  868.  
  869. ofun    _FindMethod(object i, object generic)
  870.                 /*  Instance being sent the message        */
  871.                   /*  The generic being used            */
  872. {
  873.     Method_iv_t    *miv;
  874. #if    !DPP_FASTWIDE
  875.     element    *e;
  876. #endif    
  877.     Behavior_iv_t    *civ;
  878.     GenericFunction_iv_t    *giv;
  879.     object    mo;       /*  method object found  */
  880.     object    cls;    /*  The class where the search should start    */
  881.  
  882.     /*  shouldn't have to check generic because _FindMethod is used by
  883.         macros which set the argument  */
  884.  
  885.     if (_CheckObjects_)  {
  886.         if (!IsObj(i))
  887.             gInvalidObject(generic, 1, i);
  888.         _LastGeneric_ = generic;
  889.     }
  890.  
  891.  
  892.     YIELD;
  893.  
  894.     cls = ClassOf(i);
  895.  
  896.     /*  check cache  */
  897.  
  898.     civ = SCIV(cls);
  899. /*    giv = (GenericFunction_iv_t *) direct_ivs(generic);   */
  900.     giv = (GenericFunction_iv_t *) (generic+1);
  901.  
  902. #if    !DPP_FASTWIDE
  903.     ENTERCRITICALSECTION(MC_CS);
  904.     for (e=method_cache->table[cache_entry(giv->cache_idx, civ->cache_idx)] ; e ; e=e->next)
  905.         if (e->cls == cls  &&  e->generic == generic  &&  e->level == 1)  {
  906.             volatile  ofun    meth;
  907.  
  908.             if (TRACES > TRACE_OFF)
  909.                 tracefn(i, giv, e->meth);
  910.             meth = e->miv->meth;
  911.             LEAVECRITICALSECTION(MC_CS);
  912.             return meth;
  913.         }
  914. #endif
  915.     
  916.     /*  find it the hard way   */
  917.  
  918.  
  919.     if (miv = find_method(generic, cls, 1, &mo))  {
  920. #if    !DPP_FASTWIDE
  921.         cache_add(giv->cache_idx, civ->cache_idx, generic, cls, 1, mo);
  922.         LEAVECRITICALSECTION(MC_CS);
  923. #endif
  924.  
  925.         if (TRACES > TRACE_OFF)
  926.             tracefn(i, giv, mo);
  927.  
  928.         return miv->meth;
  929.     }
  930. #if    !DPP_FASTWIDE
  931.     else
  932.         LEAVECRITICALSECTION(MC_CS);
  933. #endif    
  934.     if (!Generic(gDoesNotImplement))  /* in case kernel hasn't booted yet  */
  935.         gDoesNotImplement(cls, generic);
  936.     gDoesNotImplement(cls, generic);
  937.     return NULL;
  938. }
  939.  
  940. /* very similar to gFindMethod and gFindMethodObject */
  941. /* (if this function changes change the others) */
  942.  
  943. /*  This one aborts the program if it can't find the method  */
  944.  
  945. ofun    _FindMethod2(object cls, object generic, int lev)
  946. {
  947.     Method_iv_t    *miv;
  948. #if    !DPP_FASTWIDE
  949.     element    *e;
  950. #endif
  951.     Behavior_iv_t    *civ;
  952.     GenericFunction_iv_t    *giv;
  953.     object    mo;   /*  method object found  */
  954.  
  955.     /*  no argument checking done because this function should be called
  956.         by macros which should use correct parameters  */
  957.  
  958.     /*  check cache  */
  959.  
  960.     civ = SCIV(cls);
  961. /*    giv = (GenericFunction_iv_t *) direct_ivs(generic);   */
  962.     giv = (GenericFunction_iv_t *) (generic+1);
  963.  
  964. #if    !DPP_FASTWIDE
  965.     ENTERCRITICALSECTION(MC_CS);
  966.     for (e=method_cache->table[cache_entry(giv->cache_idx, civ->cache_idx)] ; e ; e=e->next)
  967.         if (e->cls == cls  &&  e->generic == generic  &&  e->level == lev) {
  968.             volatile  ofun    meth = e->miv->fmeth;
  969.             LEAVECRITICALSECTION(MC_CS);
  970.             return meth;
  971.         }
  972. #endif    
  973.     /*  find it the hard way   */
  974.  
  975.  
  976.     if (miv = find_method(generic, cls, lev, &mo))  {
  977. #if    !DPP_FASTWIDE
  978.         cache_add(giv->cache_idx, civ->cache_idx, generic, cls, lev, mo);
  979.         LEAVECRITICALSECTION(MC_CS);
  980. #endif
  981.         return miv->fmeth;
  982.     }
  983. #if    !DPP_FASTWIDE
  984.     else
  985.         LEAVECRITICALSECTION(MC_CS);
  986. #endif    
  987.     if (!Generic(gDoesNotImplement))  /* in case kernel hasn't booted yet  */
  988.         gDoesNotImplement(cls, generic);
  989.     gDoesNotImplement(cls, generic);
  990.     return NULL;
  991. }
  992.  
  993. /*  very similar to _FindMethod and gFindMethodObject  */
  994. /* (if this function changes change the others) */
  995.  
  996. /*  This one returns NULL if the method is not found  */
  997.  
  998. imeth    ofun    Behavior_im_gFindMethod(object self, object generic, int lev)
  999.                        /*  the class  */
  1000. {
  1001.     Method_iv_t    *miv;
  1002. #if    !DPP_FASTWIDE
  1003.     element    *e;
  1004. #endif
  1005.     Behavior_iv_t    *civ;
  1006.     GenericFunction_iv_t    *giv;
  1007.     object    mo;   /*  method object found  */
  1008.  
  1009.  
  1010.     ChkArg(generic, 2);
  1011.  
  1012.     /*  check cache  */
  1013.  
  1014.     civ = SCIV(self);
  1015. /*    giv = (GenericFunction_iv_t *) direct_ivs(generic);   */
  1016.     giv = (GenericFunction_iv_t *) (generic+1);
  1017.  
  1018. #if    !DPP_FASTWIDE
  1019.     ENTERCRITICALSECTION(MC_CS);
  1020.     for (e=method_cache->table[cache_entry(giv->cache_idx, civ->cache_idx)] ; e ; e=e->next)
  1021.         if (e->cls == self  &&  e->generic == generic  &&  e->level == lev) {
  1022.             volatile  ofun    meth = e->miv->fmeth;
  1023.             LEAVECRITICALSECTION(MC_CS);
  1024.             return meth;
  1025.         }
  1026. #endif    
  1027.     /*  find it the hard way   */
  1028.  
  1029.  
  1030.     if (miv = find_method(generic, self, lev, &mo))  {
  1031. #if    !DPP_FASTWIDE
  1032.         cache_add(giv->cache_idx, civ->cache_idx, generic, self, lev, mo);
  1033.         LEAVECRITICALSECTION(MC_CS);
  1034. #endif
  1035.         return miv->fmeth;
  1036.     }
  1037. #if    !DPP_FASTWIDE
  1038.     else
  1039.         LEAVECRITICALSECTION(MC_CS);
  1040. #endif    
  1041.     return NULL;
  1042. }
  1043.  
  1044. /*  very similar to _FindMethod and gFindMethod  */
  1045. /* (if this function changes change the others) */
  1046.  
  1047. /*  This one returns the method object instead of the C function pointer  */
  1048.  
  1049. imeth    objrtn    Behavior_im_gFindMethodObject(object self, object generic, int lev)
  1050.                        /*  the class  */
  1051. {
  1052. #if    !DPP_FASTWIDE
  1053.     element    *e;
  1054. #endif
  1055.     Behavior_iv_t    *civ;
  1056.     GenericFunction_iv_t    *giv;
  1057.     object    mo;   /*  method object found  */
  1058.  
  1059.     ChkArgTyp(generic, 2, GenericFunction_c);
  1060.  
  1061.     /*  check cache  */
  1062.  
  1063.     civ = SCIV(self);
  1064. /*    giv = (GenericFunction_iv_t *) direct_ivs(generic);   */
  1065.     giv = (GenericFunction_iv_t *) (generic+1);
  1066.  
  1067. #if    !DPP_FASTWIDE
  1068.     ENTERCRITICALSECTION(MC_CS);
  1069.     for (e=method_cache->table[cache_entry(giv->cache_idx, civ->cache_idx)] ; e ; e=e->next)
  1070.         if (e->cls == self  &&  e->generic == generic  &&  e->level == lev) {
  1071.             struct _Object_iv_t * volatile ret = e->meth;
  1072.             LEAVECRITICALSECTION(MC_CS);
  1073.             return (objrtn) ret;
  1074.         }
  1075. #endif
  1076.     
  1077.     /*  find it the hard way   */
  1078.  
  1079.  
  1080.     if (find_method(generic, self, lev, &mo))  {
  1081. #if    !DPP_FASTWIDE
  1082.         cache_add(giv->cache_idx, civ->cache_idx, generic, self, lev, mo);
  1083.         LEAVECRITICALSECTION(MC_CS);
  1084. #endif
  1085.         return mo;
  1086.     }
  1087. #if    !DPP_FASTWIDE
  1088.     else
  1089.         LEAVECRITICALSECTION(MC_CS);
  1090. #endif    
  1091.     return NULL;
  1092. }
  1093.  
  1094. /*  The remaining presumes the kernel is up  */
  1095.  
  1096. static    iv_offset_def_list    *mk_sciv_list(iv_offset_def_list *v, object sc)
  1097. {
  1098.     iv_offset_def_list    *e, *t, *n;
  1099.     Behavior_iv_t    *sciv = SCIV(sc);
  1100.  
  1101.     /*  set e to point to the last element of v  */
  1102.  
  1103.     if (e = v)
  1104.         while (e->next)
  1105.             e = e->next;
  1106.  
  1107.     /*  copy sc's list to the end of v  */
  1108.  
  1109.     if (t = sciv->all_superclasses)
  1110.         for ( ; t ; t = t->next)  {
  1111.             n = Tcalloc(iv_offset_def_list);
  1112.             *n = *t;
  1113.             n->next = NULL;
  1114.             if (!e)
  1115.                 e = v = n;
  1116.             else  {
  1117.                 e->next = n;
  1118.                 e = n;
  1119.             }
  1120.         }
  1121.  
  1122.     /*  create node for sc's direct IVs  */
  1123.  
  1124.     if (sciv->direct_iv_size)  {
  1125.         n = Tcalloc(iv_offset_def_list);
  1126.         n->superclass = sc;
  1127.         n->iv_size = sciv->direct_iv_size;
  1128.         n->next = NULL;
  1129.         if (!e)
  1130.             v = n;
  1131.         else
  1132.             e->next = n;
  1133.     }
  1134.     return(v);
  1135. }
  1136.  
  1137. static    void    remove_dup_sc(iv_offset_def_list *v)
  1138. {
  1139.     iv_offset_def_list    *m, *p;
  1140.  
  1141.     for ( ; v ; v = v->next)
  1142.         for (p=v, m=v->next ; m ; )
  1143.             if (m->superclass == v->superclass)  {
  1144.                 p->next = m->next;
  1145.                 free(m);
  1146.                 m = p->next;
  1147.             }  else  {
  1148.                 p = m;
  1149.                 m = m->next;
  1150.             }
  1151. }
  1152.  
  1153. static    int    calc_offsets(iv_offset_def_list *v)
  1154. {
  1155.     int    off = 0;
  1156.  
  1157.     for ( ; v ; v = v->next)  {
  1158.         v->iv_offset = off;
  1159.         off += v->iv_size;
  1160.     }
  1161.     return off;
  1162. }
  1163.  
  1164. static    objrtn
  1165. NewClass3(object    self,
  1166.       char         *name,
  1167.       int         ivsize,
  1168.       object     mc,            /*  metaclass    */
  1169.       int         nipib,/*  number of instances per instance block or 0    */
  1170.       int         n,            /*  number of superclasses  */
  1171.       object     *superclasses)  /*  superclass array  */
  1172. {
  1173.     object    c;    /*  new class object            */
  1174.     object    sc;    /*  superclass object            */
  1175.     int    i;    /*  indexing varaible            */
  1176.     Behavior_iv_t    *cv;    /*  new class's CVs        */
  1177.  
  1178.     USE(self);
  1179.     c = Behavior_im_gNew(mc);
  1180.     cv = SCIV(c);
  1181.     new_class(c, cv, name);
  1182.     cv->direct_iv_size = EVEN(ivsize);
  1183.     cv->direct_superclasses = Tncalloc(object, n);
  1184.     cv->n_direct_superclasses = n;
  1185.  
  1186.     for (i=0 ; i < n ; i++)  {
  1187.         cv->direct_superclasses[i] = sc = superclasses[i];
  1188.         cv->all_superclasses = mk_sciv_list(cv->all_superclasses, sc);
  1189.         mk_subclass_link(sc, c);
  1190.     }
  1191.  
  1192.     remove_dup_sc(cv->all_superclasses);
  1193.     
  1194.     cv->direct_iv_offset  = calc_offsets(cv->all_superclasses);
  1195.  
  1196.     cv->effective_iv_size  = cv->direct_iv_size + cv->direct_iv_offset;
  1197.  
  1198.     if (nipib)
  1199.         cv->nipib = nipib;
  1200.     else  {
  1201.         cv->nipib = cv->effective_iv_size / 50;
  1202.         cv->nipib = cv->nipib ? cv->nipib : 1;
  1203.     }
  1204.  
  1205.     return(c);
  1206. }
  1207.  
  1208. #if    DPP_STRATEGY == 1
  1209. static    objrtn    Class_cm_gNewStdClass(object self, char *name, int ivsize, object mc, 
  1210.               int nipib, object superclasses, ...)
  1211. #else
  1212. static    objrtn    Class_cm_gNewStdClass(object self, char *name, int ivsize, object mc, 
  1213.               int nipib, object superclasses, va_list _rest_)
  1214. #endif
  1215. {
  1216.     object    c;    /*  new class object            */
  1217.     object    sc;    /*  superclass object            */
  1218.     int    n;    /*  number of superclasses        */
  1219.     object    scvp[MIS];/*  array of superclasses        */
  1220.     char    buf[80];
  1221.     MAKE_REST(superclasses);
  1222.  
  1223.     ChkArg(mc, 4);
  1224.     if (!IsClass(mc))
  1225.         gError(self, "gNewStdClass argument 4 is not a class.\n");
  1226.  
  1227.     if (superclasses)
  1228.         for (n=0, sc=superclasses ; sc && n < MIS ; sc = GetArg(object), ++n)  {
  1229.             ChkArg(sc, n+6);
  1230.             if (!IsClass(sc))  {
  1231.                 sprintf(buf, "gNewStdClass argument %d is not a class.\n", n+6);
  1232.                 gError(self, buf);
  1233.             }
  1234.             scvp[n] = sc;
  1235.         }
  1236.     else  {
  1237.         n = 1;
  1238.         scvp[0] = Object_c;
  1239.     }
  1240.     if (n == MIS)  {
  1241.         sprintf(buf, "Attempt to create class %s with more than %d superclasses", name, MIS);
  1242.         gError(self, buf);
  1243.     }
  1244.  
  1245.     n = n > MIS ? MIS : n;
  1246.  
  1247.     c = NewClass3(self, name, ivsize, mc, nipib, n, scvp);
  1248.     
  1249.     return(c);
  1250. }
  1251.  
  1252. #if    DPP_STRATEGY == 1
  1253. static objrtn    Class_cm_gNewClass(object self, char *name, int ivsize, int cvsize, 
  1254.              object superclasses, ...)
  1255. #else
  1256. static objrtn    Class_cm_gNewClass(object self, char *name, int ivsize, int cvsize, 
  1257.              object superclasses, va_list _rest_)
  1258. #endif
  1259. {
  1260.     object    c;    /*  new class object            */
  1261.     object    sc;    /*  superclass object            */
  1262.     int    n;    /*  number of superclasses        */
  1263.     object    scvp1[MIS];/*  array of superclasses        */
  1264.     object    scvp2[MIS];/*  array of meta superclasses    */
  1265.     object    mc;    /*  metaclass                */
  1266.     char    meta[100];    /*  metaclass name        */
  1267.     MAKE_REST(superclasses);
  1268.     
  1269.     if (superclasses)
  1270.         for (n=0, sc=superclasses ; sc && n < MIS ; sc = GetArg(object), ++n)  {
  1271.             ChkArg(sc, n+5);
  1272.             if (!IsClass(sc))  {
  1273.                 sprintf(meta, "gNewClass(Class..) argument %d is not a class.\n", n+5);
  1274.                 gError(self, meta);
  1275.             }
  1276.             scvp1[n] = sc;
  1277.             scvp2[n] = ClassOf(sc);
  1278.         }
  1279.     else  {
  1280.         scvp1[0] = Object_c;
  1281.         scvp2[0] = metaObject;
  1282.         n = 1;
  1283.     }
  1284.     if (n == MIS)  {
  1285.         sprintf(meta, "Attempt to create class %s with more than %d superclasses", name, MIS);
  1286.         gError(self, meta);
  1287.     }
  1288.     
  1289.     strcpy(meta, "meta");
  1290.     strcat(meta, name);
  1291.  
  1292.     n = n > MIS ? MIS : n;
  1293.  
  1294.     mc = NewClass3(self, meta, cvsize, MetaClass_c, 1, n, scvp2);
  1295.     c = NewClass3(self, name, ivsize, mc, 0, n, scvp1);
  1296.     
  1297.     return(c);
  1298. }
  1299.  
  1300. void    *GetIVptr(object obj, object cls)
  1301. {
  1302.     Behavior_iv_t        *cv;
  1303.     iv_offset_def_list    *v;
  1304.  
  1305.     /*  cls not validated for the sake of speed  */
  1306.  
  1307.     cv = SCIV(ClassOf(obj));
  1308.     if (cls == ClassOf(obj))
  1309.         return (char *) obj + cv->direct_iv_offset;
  1310.     for (v=cv->all_superclasses ; v ; v=v->next)
  1311.         if (v->superclass == cls)
  1312.             return (char *) obj + v->iv_offset;
  1313.     return NULL;
  1314. }
  1315.  
  1316. imeth    objrtn    Object_im_gDispose(object self)
  1317. {
  1318.     Behavior_iv_t    *cv;
  1319.     free_list    *fl;
  1320.  
  1321.     if (self->tag & ALLOC_STACK) {
  1322.         self->tag = (OBJ_FREE | ALLOC_STACK);
  1323.         return NULL;
  1324.     }
  1325.     if (self->tag & OBJ_FREE)
  1326.         return NULL;
  1327.     self->tag = (OBJ_FREE | ALLOC_HEAP);
  1328.     cv = SCIV(ClassOf(self));
  1329.     ENTERCRITICALSECTION(cv->cs);
  1330. #ifndef    BOEHM_GC
  1331.     fl = (free_list *) self;
  1332.     fl->next = cv->fl;
  1333.     cv->fl = fl;
  1334.     cv->nai++;
  1335. /*
  1336.     set_class(self, NULL);
  1337.     free(self);
  1338. */
  1339. #endif
  1340.     cv->ni--;
  1341.     CMU -= cv->effective_iv_size;
  1342.     LEAVECRITICALSECTION(cv->cs);
  1343.     return NULL;
  1344. }
  1345.  
  1346. /*  garbage collector code   */
  1347.  
  1348. /*   non-recursive marker   */
  1349.  
  1350. cmeth    void    Dyance_cm_gMarkObject(object self, object obj)
  1351. {
  1352. #ifdef    BOEHM_GC
  1353.     USE(self);
  1354.     USE(obj);
  1355. #else
  1356.     char    **p;
  1357.     short    sz;
  1358.     object    rtn = NULL, nxt;
  1359.  
  1360.     USE(self);
  1361.  recurse:
  1362.     obj->tag = OBJ_MARKED | (ALLOC_MASK & obj->tag);
  1363.     p =  (char **) (obj + 1);
  1364.     sz = SCIV(ClassOf(obj))->effective_iv_size -
  1365.         (EVEN(sizeof(Object_iv_t)) + sizeof(char *));
  1366.     while (sz >= 0)  {
  1367.         nxt = *((object *) ((char *) p + sz));
  1368.         if (IsObj(nxt))  {
  1369.             if (nxt->tag & OBJ_USED)  {
  1370.                 /*  mark & save sz  */
  1371.                 obj->tag = OBJ_MARKED | (ALLOC_MASK & obj->tag);
  1372.                 obj->siz = sz;
  1373.  
  1374.                 /*  reverse link  */
  1375.                 *((object *) ((char *) p + sz)) = rtn;
  1376.                 rtn = obj;
  1377.  
  1378.                 /*  create new environment  */
  1379.                 obj = nxt;
  1380.  
  1381.                 /*  recurse  */
  1382.                 goto recurse;
  1383.             }
  1384.  pop_recursion:
  1385. #ifdef    ALIGN4
  1386.         ;}
  1387.         sz -= 4;
  1388. #else
  1389.             sz -= 4;
  1390.         }  else
  1391.             sz -= 2;
  1392. #endif
  1393.     }
  1394.  
  1395.     if (!rtn)
  1396.         return;    /*  all done  */
  1397.  
  1398.     /*  get old sz  */
  1399.     sz = rtn->siz;
  1400.     rtn->siz = 0;
  1401.  
  1402.     p = (char **) (rtn + 1);
  1403.     nxt = rtn;
  1404.     rtn = *((object *) ((char *) p + sz));
  1405.     *((object *) ((char *) p + sz)) = obj;
  1406.  
  1407.     /*  pop recursion  */
  1408.     obj = nxt;
  1409.     goto pop_recursion;
  1410. #endif    /*  !BOEHM_GC  */
  1411. }
  1412.  
  1413. cmeth    void    Dynace_cm_gMarkRange(object self, char _HUGE **from, char _HUGE **to)
  1414. {
  1415. #ifdef    BOEHM_GC
  1416.     USE(self);
  1417.     USE(from);
  1418.     USE(to);
  1419. #else
  1420.     object    obj;
  1421.     
  1422.     USE(self);
  1423. #ifdef    ALIGN4
  1424.     from = (char _HUGE **) EVEN(from);
  1425.     to   = (char _HUGE **) EVEN(to);
  1426. #else
  1427.     if ((long) from & 1L)
  1428.         from = (char _HUGE **) ((char _HUGE *) from + 1);
  1429.     if ((long) to & 1L)
  1430.         to = (char _HUGE **) ((char _HUGE *) to + 1);
  1431. #endif
  1432.     while (from < to)  {
  1433.         if (IsObj((object)*from))  {
  1434.             obj = (object) *from;
  1435.             if (obj->tag & OBJ_USED)
  1436.                 Dyance_cm_gMarkObject(Dynace_c, obj);
  1437. #ifdef    ALIGN4
  1438.         }
  1439.         from = (char _HUGE **)((char _HUGE *) from + 4);
  1440. #else
  1441.             from = (char _HUGE **)((char _HUGE *) from + 4);
  1442.         }  else
  1443.             from = (char _HUGE **)((char _HUGE *) from + 2);
  1444. #endif
  1445.     }
  1446. #endif  /*  !BOEHM_GC   */
  1447. }
  1448.  
  1449. #ifdef    BOEHM_GC
  1450.  
  1451. static    void    dispose_boehm_gc(object obj, void *p)
  1452. {
  1453.     Behavior_iv_t    *cv;
  1454.  
  1455.     USE(p);
  1456.     INHIBIT_THREADER;
  1457.     cv = SCIV(ClassOf(obj));
  1458.     if (obj->tag & OBJ_USED  &&  !cv->ncg)
  1459.         gGCDispose(obj);
  1460.     ENABLE_THREADER;
  1461. }
  1462.  
  1463. #else
  1464.  
  1465. cmeth    object    Dynace_cm_gDumpObjects(object self, char *file, int type)
  1466. {
  1467.     object    c, obj;
  1468.     Behavior_iv_t    *cv;
  1469.     instance_block    *ib;
  1470.     int    is=0, n;
  1471.     long    num;
  1472.     char    *p;
  1473.     FILE    *fp;
  1474.  
  1475.     USE(type);
  1476.     fp = fopen(file, "w");
  1477.     if (!fp)
  1478.         return NULL;
  1479.     ENTERCRITICALSECTION(MCL_CS);
  1480.     for (c=MCL ; c ; c=cv->next)  {
  1481.         cv = SCIV(c);
  1482.         if (ib = cv->ib)
  1483.             is =  cv->effective_iv_size;
  1484.         num = 0L;
  1485.         while (ib)  {
  1486.             p = (char *) (ib + 1);
  1487.             for (n=0 ; n++ != cv->nipib ; )  {
  1488.                 obj = (object) p;
  1489.                 if (obj->tag & OBJ_USED)
  1490.                     num++;
  1491.                 p += is;
  1492.             }
  1493.             ib = ib->next;
  1494.         }
  1495.         if (num)
  1496.             fprintf(fp, "%ld instances of %s\n", num, cv->name);
  1497.     }
  1498.     LEAVECRITICALSECTION(MCL_CS);
  1499.     fclose(fp);
  1500.     return self;
  1501. }
  1502.  
  1503. static    void    rebuild_free_list(Behavior_iv_t *cv, int is)
  1504. {
  1505.     instance_block    *ib;
  1506.     int    i;
  1507.     free_list    *fl;
  1508.  
  1509.     cv->fl = NULL;
  1510.     for (ib=cv->ib ; ib ; ib=ib->next)  {
  1511.         fl = (free_list *) (ib + 1);
  1512.         for (i=0 ; i++ != cv->nipib ; )  {
  1513.             if (((object) fl)->tag & OBJ_FREE)  {
  1514.                 fl->next = cv->fl;
  1515.                 cv->fl = fl;
  1516.             }
  1517.             fl = (free_list *) ((char *) fl + is);
  1518.         }
  1519.     }
  1520. }
  1521.  
  1522. static    void    gc_sweep(void)
  1523. {
  1524.     object    c, obj;
  1525.     Behavior_iv_t    *cv;
  1526.     instance_block    *ib;
  1527.     instance_block    *pib=NULL;    /*  previous instance block  */
  1528.     instance_block    *nib;        /*  next instance block  */
  1529.     int    is=0, n;
  1530.     int    f;    /*  the number of free objects in a block  */
  1531.     int    rfl;    /*  rebuild free list            */
  1532.     char    *p;
  1533.     gGCDispose_t    dfun=NULL;    /*  dispose function        */
  1534.  
  1535.     ENTERCRITICALSECTION(MCL_CS);
  1536.     MetaClass_c->tag = (OBJ_USED | ALLOC_HEAP);  /*  MetaClass not in any storage bin */
  1537.     for (c=MCL ; c ; c=cv->next)  {
  1538.         cv = SCIV(c);
  1539.         rfl = 0;
  1540.         if (ib = cv->ib)  {
  1541.             dfun = imcPointer(c, gGCDispose);
  1542.             is =  cv->effective_iv_size;
  1543.             pib = NULL;
  1544.         }
  1545.         while (ib)  {
  1546.             p = (char *) (ib + 1);
  1547.             for (f=n=0 ; n++ != cv->nipib ; )  {
  1548.                 obj = (object) p;
  1549.                 if (obj->tag & OBJ_USED)  {
  1550.                     if (!cv->ncg)  {
  1551.                         (*(object(*)(object))dfun)(obj);
  1552.                         ++f;
  1553.                     }
  1554.                 }  else if (obj->tag & OBJ_MARKED) {
  1555.                     obj->tag = OBJ_USED | (ALLOC_MASK & obj->tag);
  1556.                     obj->siz = 0;
  1557.                 }  else  /*  already free  */
  1558.                     ++f;
  1559.                 p += is;
  1560.             }
  1561.             if (f == cv->nipib)  {  /*  all objs freed  */
  1562.                 if (pib)
  1563.                     pib->next = nib = ib->next;
  1564.                 else
  1565.                     cv->ib = nib = ib->next;
  1566.                 free(ib);
  1567.                 ib = nib;
  1568.                 cv->nib--;
  1569.                 cv->nai -= cv->nipib;
  1570.                 rfl = 1;
  1571.             }  else  {
  1572.                 pib = ib;
  1573.                 ib = ib->next;
  1574.             }
  1575.         }
  1576.         if (rfl)
  1577.             rebuild_free_list(cv, is);
  1578.     }
  1579.     LEAVECRITICALSECTION(MCL_CS);
  1580. }
  1581.  
  1582. #endif   /*  !BOEHM_GC  */
  1583.  
  1584.  
  1585. static    void    get_mem_stats(void)
  1586. {
  1587.     object    c;
  1588.     Behavior_iv_t    *cv;
  1589.     int    is;
  1590.     long    m = 0L;
  1591.  
  1592.     ENTERCRITICALSECTION(MCL_CS);
  1593.     for (c=MCL ; c ; c=cv->next)  {
  1594.         cv = SCIV(c);
  1595.         is = cv->effective_iv_size;
  1596.         m += cv->ni * is;
  1597.     }
  1598.     LEAVECRITICALSECTION(MCL_CS);
  1599.     if (m > MBU)
  1600.         MBU = m;
  1601.     CMU = m;
  1602. }
  1603.  
  1604.  
  1605. #if    defined(MSC32)  ||  defined(BC32)
  1606. #define MARK_REG(r)                \
  1607.     __asm    { mov    c, r  }            \
  1608.     if (IsObj(c)  &&  c->tag & OBJ_USED)    \
  1609.         Dyance_cm_gMarkObject(Dynace_c, c)
  1610. #endif
  1611.  
  1612.  
  1613. #if    defined(unix)  &&  defined(i386)
  1614. #define MARK_REG(r)                    \
  1615.     __asm__    ("movl %%" #r ",%0" : "=g" (c));    \
  1616.     if (IsObj(c)  &&  c->tag & OBJ_USED)        \
  1617.         Dyance_cm_gMarkObject(Dynace_c, c)
  1618. #endif
  1619.  
  1620.  
  1621. cmeth    objrtn    Dynace_cm_gGC(object self)
  1622. {
  1623. #ifdef    BOEHM_GC
  1624.     INHIBIT_THREADER;
  1625.     GC_gcollect();
  1626. #else
  1627.     GMR    *p;
  1628.     object    c;
  1629.     Behavior_iv_t    *cv;
  1630.     
  1631.     INHIBIT_THREADER;
  1632. #ifdef sparc
  1633.     asm("t 3");    /* flush out registers onto the stack */
  1634. #endif
  1635.     Dynace_cm_gMarkRange(Dynace_c, (char _HUGE **) &self, (char _HUGE **) StackBeg);
  1636.     Dyance_cm_gMarkObject(Dynace_c, MCL);
  1637.     Dyance_cm_gMarkObject(Dynace_c, MGL);
  1638.     Dyance_cm_gMarkObject(Dynace_c, MML);
  1639. #if defined(MSC32)  ||  defined(BC32)  ||  (defined(unix) && defined(i386))
  1640.     MARK_REG(eax);
  1641.     MARK_REG(ebx);
  1642.     MARK_REG(ecx);
  1643.     MARK_REG(edx);
  1644.     MARK_REG(esi);
  1645.     MARK_REG(edi);
  1646.     MARK_REG(ebp);
  1647. #endif
  1648.     for (p=LGMR ; p ; p=p->next)
  1649.         Dynace_cm_gMarkRange(Dynace_c, (char _HUGE **) p->beg,
  1650.                (char _HUGE **)((char *) p->beg + p->size));
  1651.     for (c=MCL ; c ; c = cv->next)  {
  1652.         cv = SCIV(c);
  1653.         if (cv->markfun)
  1654.             (*(void(*)(object))cv->markfun)(c);
  1655.     }
  1656.     gc_sweep();
  1657. #endif  /*  !BOEHM_GC  */
  1658.     get_mem_stats();
  1659.     ENABLE_THREADER;
  1660.     return self;
  1661. }
  1662.  
  1663. /*  misc kernel methods  */
  1664.  
  1665. cmeth    void    *Dynace_cm_gRegisterMemory(object self, void *beg, long size)
  1666. {
  1667.     GMR    *p;
  1668.  
  1669.     USE(self);
  1670.     ENTERCRITICALSECTION(GMR_CS);
  1671.     p = new_gmr();
  1672.     p->prev = NULL;
  1673.     if (p->next = LGMR)
  1674.         LGMR->prev = p;
  1675.     LGMR = p;
  1676.     p->beg = beg;
  1677.     p->size = size;
  1678.     LEAVECRITICALSECTION(GMR_CS);
  1679.     return (void *) p;
  1680. }
  1681.  
  1682. cmeth    void    Dynace_cm_gRemoveRegisteredMemory(object self, void *pp)
  1683. {
  1684.     GMR    *p = (GMR *) pp;
  1685.     USE(self);
  1686.     ENTERCRITICALSECTION(GMR_CS);
  1687.     if (p->next)
  1688.         p->next->prev = p->prev;
  1689.     if (p->prev)
  1690.         p->prev->next = p->next;
  1691.     else
  1692.         LGMR = p->next;
  1693.     free_gmr(p);
  1694.     LEAVECRITICALSECTION(GMR_CS);
  1695. }
  1696.  
  1697. cmeth    void    *Dynace_cm_gChangeRegisteredMemory(object self, void *pp, void *beg, long size)
  1698. {
  1699.     GMR    *p = (GMR *) pp;
  1700.     USE(self);
  1701.     p->beg = beg;
  1702.     p->size = size;
  1703.     return (void *) p;
  1704. }
  1705.  
  1706. cmeth    long    Dynace_cm_gMaxAfterGC(object self)
  1707. {
  1708.     USE(self);
  1709.     return MBU ? MBU : CMU;
  1710. }
  1711.  
  1712. cmeth    long    Dynace_cm_gMaxMemUsed(object self)
  1713. {
  1714.     USE(self);
  1715.     return MSU;
  1716. }
  1717.  
  1718. cmeth    long    Dynace_cm_gCurMemUsed(object self)
  1719. {
  1720.     USE(self);
  1721.     return CMU;
  1722. }
  1723.  
  1724. imeth    int    Object_im_gEqual(object self, object obj2)
  1725. {
  1726.     register    char    *p1, *p2;
  1727.     register    int    sz;
  1728.  
  1729.     if (EQ(self, obj2))
  1730.         return 1;
  1731.     ChkArg(obj2, 2);
  1732.     if (NEQ(ClassOf(self), ClassOf(obj2)))
  1733.         return 0;
  1734.     sz = SCIV(ClassOf(self))->effective_iv_size - EVEN(sizeof(Object_iv_t));
  1735.     p1 = (char *) (self + 1);
  1736.     p2 = (char *) (obj2 + 1);
  1737.     while (sz--)
  1738.         if (*p1++ != *p2++)
  1739.             return 0;
  1740.     return 1;
  1741. }
  1742.  
  1743. imeth    objrtn    Object_im_gCopy(object self)
  1744. {
  1745.     object    obj2;
  1746.     register    int    sz;
  1747.  
  1748.     obj2 = Behavior_im_gNew(ClassOf(self));
  1749.     sz = SCIV(ClassOf(self))->effective_iv_size;
  1750.     memcpy(obj2 + 1, self + 1, sz-EVEN(sizeof(Object_iv_t)));
  1751.     return obj2;
  1752. }
  1753.  
  1754. imeth    int    Object_im_gSize(object self)
  1755. {
  1756.     return SCIV(ClassOf(self))->effective_iv_size -    EVEN(sizeof(Object_iv_t));
  1757. }
  1758.  
  1759. imeth    int    Object_im_gBasicSize(object self)
  1760. {
  1761.     return SCIV(ClassOf(self))->effective_iv_size;
  1762. }
  1763.  
  1764. imeth    int    Behavior_im_gInstanceSize(object self)
  1765. {
  1766.     return SCIV(self)->effective_iv_size;
  1767. }
  1768.  
  1769. cmeth    int    Dynace_cm_gTrace(object self, int mode)
  1770. {
  1771.     int    pmode = TRACES;
  1772.     USE(self);
  1773.     TRACES = mode;
  1774.     return pmode;
  1775. }
  1776.  
  1777. static    void    init_critical_sections()
  1778. {
  1779.     INITIALIZECRITICALSECTION(_CI_CS_);
  1780.     INITIALIZECRITICALSECTION(MCL_CS);
  1781.     INITIALIZECRITICALSECTION(MGL_CS);
  1782.     INITIALIZECRITICALSECTION(MML_CS);
  1783.     INITIALIZECRITICALSECTION(GMR_CS);
  1784. #ifdef    SEGMENTED_MEMORY
  1785.     INITIALIZECRITICALSECTION(MSL_CS);
  1786. #else
  1787.     INITIALIZECRITICALSECTION(PTR_CS);
  1788. #endif
  1789. #if    !DPP_FASTWIDE
  1790.     INITIALIZECRITICALSECTION(MC_CS);
  1791. #endif
  1792. #ifdef    USE_SIGNAL
  1793.     INITIALIZECRITICALSECTION(SSE_CS);
  1794. #endif
  1795. }
  1796.  
  1797. void    InitKernel(void *sb, int nc)  /*  stack beginning, # of classes  */
  1798. {
  1799.     Behavior_iv_t    *cv;
  1800.     int    s;
  1801.     static    int    once = 0;
  1802.  
  1803.     if (once++)
  1804.         return;
  1805.  
  1806.     init_critical_sections();
  1807.  
  1808.     StackBeg = (char *) sb;
  1809.  
  1810.     NUM_CLASSES = nc;
  1811.  
  1812.     /*  Build MetaClass by hand  */
  1813.  
  1814.     s = EVEN(sizeof(Object_iv_t)) + EVEN(sizeof(Behavior_iv_t));
  1815.     MetaClass_c = (object) Tncalloc(char, s);
  1816.     add_ptr((char *) MetaClass_c, s);
  1817.     MetaClass_c->tag = (OBJ_USED | ALLOC_HEAP);
  1818.     cv = SCIV(MetaClass_c);
  1819.     new_class(MetaClass_c, cv, "MetaClass");
  1820.     cv->direct_iv_size = 0;
  1821.     cv->effective_iv_size = s;
  1822.     cv->nipib = 6;
  1823.     
  1824.  
  1825. #define MCLASS(c)        c = defClass(MetaClass_c, #c, s, 0, 1)
  1826. #define PCLASS(c, esz, dsz, n)    c##_c = defClass(meta##c, #c, esz, dsz, n)
  1827. #define BCLASS(c, dsz, n)    c##_c = defClass(meta##c, #c, EVEN(sizeof(Object_iv_t))+sizeof(dsz), sizeof(dsz), n)
  1828.  
  1829.  
  1830.  
  1831.     MCLASS(metaObject);
  1832.     PCLASS(Object, sizeof(Object_iv_t), sizeof(Object_iv_t), 1);
  1833.     MCLASS(metaBehavior);
  1834.     PCLASS(Behavior, s, sizeof(Behavior_iv_t), 1);
  1835.     MCLASS(metaClass);
  1836.     PCLASS(Class, s, 0, 1);
  1837.     MCLASS(metaMetaClass);
  1838.  
  1839.     MCLASS(metaMethod);
  1840.     MCLASS(metaGenericFunction);
  1841.  
  1842.     BCLASS(Method, Method_iv_t, 30);
  1843.     BCLASS(GenericFunction, GenericFunction_iv_t, 15);
  1844.  
  1845.     set_class(MetaClass_c, metaMetaClass);
  1846.  
  1847.     set_superclass(Object_c, NULL);
  1848.     set_superclass(Behavior_c, Object_c);
  1849.     set_superclass(Class_c, Behavior_c);
  1850.     set_superclass(MetaClass_c, Behavior_c);
  1851.     set_superclass(metaObject, Class_c);
  1852.     set_superclass(metaBehavior, metaObject);
  1853.     set_superclass(metaClass, metaBehavior);
  1854.     set_superclass(metaMetaClass, metaBehavior);
  1855.     set_superclass(Method_c, Object_c);
  1856.     set_superclass(metaMethod, metaObject);
  1857.     set_superclass(GenericFunction_c, Object_c);
  1858.     set_superclass(metaGenericFunction, metaObject);
  1859.  
  1860. #if    !DPP_FASTWIDE    
  1861.     ENTERCRITICALSECTION(MC_CS);
  1862.     create_cache(Crows, Ccols);    /*  generics, classes  */
  1863.     LEAVECRITICALSECTION(MC_CS);
  1864. #endif
  1865.  
  1866.     Generic(gNew) = GenericFunction_cm_gNewWithStr(GenericFunction_c, "gNew");
  1867.     Generic(gNewClass) = GenericFunction_cm_gNewWithStr(GenericFunction_c, "gNewClass");
  1868.     Generic(gNewMethod) = GenericFunction_cm_gNewWithStr(GenericFunction_c, "gNewMethod");
  1869.     Generic(gNewWithStr) = GenericFunction_cm_gNewWithStr(GenericFunction_c, "gNewWithStr");
  1870.  
  1871.     Method_cm_gNewMethod(Method_c, "gNewMethod", metaMethod, Generic(gNewMethod), (ofun) Method_cm_gNewMethod, (ofun) Method_cm_gNewMethod);
  1872.  
  1873.     /*  The next line is very critical because it is the first use of
  1874.         the dynamic dispatching.  If using the jumpto assembler start
  1875.         tracing the assembler stuff from here.  */
  1876.     gNewMethod(Method_c, "gNewClass", metaClass, Generic(gNewClass), (ofun) Class_cm_gNewClass, (ofun) Class_cm_gNewClass);
  1877.  
  1878.     cMethodFor(GenericFunction, gNewWithStr, GenericFunction_cm_gNewWithStr);
  1879.     iMethodFor(Behavior, gNew, Behavior_im_gNew);
  1880.  
  1881.     InitGenerics();
  1882.  
  1883.     cMethodFor(Class, gNewStdClass, Class_cm_gNewStdClass);
  1884.     iMethodFor(Behavior, vNew, Behavior_im_gNew);
  1885.     iMethodFor(Behavior, gAlloc, Behavior_im_gNew);
  1886.     iMethodFor(Behavior, gStackAlloc, Behavior_im_gStackAlloc);
  1887.  
  1888.     Object_initialize();
  1889.     iMethodFor(Object, gDispose, Object_im_gDispose);
  1890.     iMethodFor(Object, gDeepDispose, Object_im_gDispose);
  1891.     iMethodFor(Object, gGCDispose, Object_im_gDispose);
  1892.     iMethodFor(Object, gEqual, Object_im_gEqual);
  1893.     iMethodFor(Object, gSize, Object_im_gSize);
  1894.     iMethodFor(Object, gBasicSize, Object_im_gBasicSize);
  1895.     iMethodFor(Object, gCopy, Object_im_gCopy);
  1896.     iMethodFor(Object, gDeepCopy, Object_im_gCopy);
  1897.  
  1898.     GenericFunction_initialize();
  1899.  
  1900.     Method_initialize();
  1901.  
  1902.     Behavior_initialize();
  1903.     iMethodFor(Behavior, gFindMethod, Behavior_im_gFindMethod);
  1904.     iMethodFor(Behavior, gFindMethodObject, Behavior_im_gFindMethodObject);
  1905.     iMethodFor(Behavior, gInstanceSize, Behavior_im_gInstanceSize);
  1906.  
  1907.     MetaClass_initialize();
  1908.  
  1909.     Class_initialize();
  1910.     iMethodFor(Class, gFindClass, Class_cm_gFindClass);
  1911.  
  1912.     Dynace_initialize();
  1913.     cMethodFor(Dynace, gGC, Dynace_cm_gGC);
  1914. #if    !DPP_FASTWIDE
  1915.     cMethodFor(Dynace, gResizeMethodCache, Dynace_cm_gResizeMethodCache);
  1916. #endif
  1917.     cMethodFor(Dynace, gSetMemoryBufferArea, Dynace_cm_gSetMemoryBufferArea);
  1918.     cMethodFor(Dynace, gRegisterMemory, Dynace_cm_gRegisterMemory);
  1919.     cMethodFor(Dynace, gRemoveRegisteredMemory, Dynace_cm_gRemoveRegisteredMemory);
  1920.     cMethodFor(Dynace, gChangeRegisteredMemory, Dynace_cm_gChangeRegisteredMemory);
  1921.     cMethodFor(Dynace, gTrace, Dynace_cm_gTrace);
  1922.     cMethodFor(Dynace, gMarkRange, Dynace_cm_gMarkRange);
  1923.     cMethodFor(Dynace, gMarkObject, Dyance_cm_gMarkObject);
  1924.     cMethodFor(Dynace, gMaxMemUsed, Dynace_cm_gMaxMemUsed);
  1925.     cMethodFor(Dynace, gCurMemUsed, Dynace_cm_gCurMemUsed);
  1926.     cMethodFor(Dynace, gMaxAfterGC, Dynace_cm_gMaxAfterGC);
  1927.     cMethodFor(Dynace, gDumpObjects, Dynace_cm_gDumpObjects);
  1928.  
  1929.     gTrace(Generic(gTracePrint), TRACE_OFF);
  1930.     gTrace(Generic(gTrace), TRACE_OFF);
  1931. }
  1932.  
  1933.  
  1934.  
  1935. /*
  1936.  *
  1937.  *    Copyright (c) 1993-1996 Algorithms Corporation
  1938.  *    3020 Liberty Hills Drive
  1939.  *    Franklin, TN  37067
  1940.  *
  1941.  *    ALL RIGHTS RESERVED.
  1942.  *
  1943.  *
  1944.  *
  1945.  */
  1946.  
  1947.  
  1948.